package com.woniuxy.health.commodity.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniuxy.health.commodity.constant.Constant;
import com.woniuxy.health.commodity.dto.GoodsTypeDTO;
import com.woniuxy.health.commodity.mapper.GoodsTypeMapper;
import com.woniuxy.health.vo.GoodsTypeVO;
import com.woniuxy.health.model.commodity.GoodsType;
import com.woniuxy.health.commodity.service.IGoodsTypeService;
import com.woniuxy.health.vo.PageVO;
import com.woniuxy.utils.result.Asserts;
import com.woniuxy.utils.result.ResultCodeEnum;
import org.springframework.context.annotation.Bean;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author woniuxy
 * @since 2023-09-04
 */
@Service
public class GoodsTypeServiceImpl extends ServiceImpl<GoodsTypeMapper, GoodsType> implements IGoodsTypeService {

    private final GoodsTypeMapper goodsTypeMapper;
    private final RedisTemplate redisTemplate;

    public GoodsTypeServiceImpl(GoodsTypeMapper goodsTypeMapper, RedisTemplate redisTemplate){
        this.goodsTypeMapper = goodsTypeMapper;
        this.redisTemplate = redisTemplate;
    }

    @Override
    public PageVO getPageInfo(GoodsTypeDTO goodsTypeDTO) {

        if (goodsTypeDTO.getDateRange().length < 2){
            goodsTypeDTO.setDateRange(new LocalDate[]{null, null});
        }

//        PageVO pageVO = new PageVO<>();
//
//        List<GoodsTypeVO> list = goodsTypeMapper.selectByCondition(goodsTypeDTO);
//        List<GoodsTypeVO> goodsTypeVOS = new ArrayList<>();
//        for (int i = 0; i < list.size();) {
//            GoodsTypeVO goodsTypeVO = new GoodsTypeVO();
//            List<String> subTypes = new ArrayList<>();
//            int j = 0;
//            BeanUtil.copyProperties(list.get(i), goodsTypeVO);
//            for (int i1 = 0; i1 < list.size(); i1++) {
//                if (list.get(i1).getId().equals(list.get(i).getId())) {
//                    subTypes.add(list.get(i1).getSubType());
//                    j++;
//                }
//            }
//            i += j;
//            goodsTypeVO.setSubTypes(subTypes);
//            goodsTypeVOS.add(goodsTypeVO);
//        }
//
//        List range = redisTemplate.opsForList().range(Constant.ALL_PTYPE, 0, -1);
//        List list1 = (List) range.get(0);
//        pageVO.setTotal((long) list1.size());
//        pageVO.setRecords(goodsTypeVOS);

        // 查出全部分类
        List<GoodsType> allTypes = goodsTypeMapper
                .selectList(Wrappers.lambdaQuery(GoodsType.class)
                        .eq(Objects.nonNull(goodsTypeDTO.getTypeId()), GoodsType::getId, goodsTypeDTO.getTypeId())
                        .or()
                        .eq(Objects.nonNull(goodsTypeDTO.getTypeId()), GoodsType::getParentId, goodsTypeDTO.getTypeId())
                        .between(goodsTypeDTO.getDateRange()[0] != null,
                                GoodsType::getCreateTime,
                                goodsTypeDTO.getDateRange()[0],
                                goodsTypeDTO.getDateRange()[1]));

        PageVO pageVO = new PageVO<>();

        // 找所有一级分类
        List<GoodsTypeVO> levelOne = allTypes.stream()
                .filter(e -> e.getParentId() == 0)
                .map(e -> {
                    GoodsTypeVO levelOneVo = new GoodsTypeVO();
                    BeanUtil.copyProperties(e, levelOneVo);
                    return levelOneVo;
                })
                .collect(Collectors.toList());

        // 对一级分类进行分页查询
        List<GoodsTypeVO> pageInfo;
        if(levelOne.size() - ((goodsTypeDTO.getPageNum()- 1) * goodsTypeDTO.getPageSize()) <= goodsTypeDTO.getPageSize()){
            List<GoodsTypeVO> collect =
                    levelOne.stream()
                            .skip((goodsTypeDTO.getPageNum() - 1) * goodsTypeDTO.getPageSize())
                            .collect(Collectors.toList());
            pageInfo = getSubType(collect, allTypes);
        }else {
            List<GoodsTypeVO> collect =
                    levelOne.stream()
                            .skip((goodsTypeDTO.getPageNum() - 1) * goodsTypeDTO.getPageSize())
                            .limit(goodsTypeDTO.getPageSize())
                            .collect(Collectors.toList());
            pageInfo = getSubType(collect, allTypes);
        }
        pageVO.setTotal((long) levelOne.size());
        pageVO.setRecords(pageInfo);

        return pageVO;
    }

    // 找所有一级品类
    @Override
    public List<GoodsType> getAllLevelOne() {
        // redis中有，则取出
        if (redisTemplate.hasKey(Constant.ALL_PTYPE)){
            List range = redisTemplate.opsForList().range(Constant.ALL_PTYPE, 0, -1);
            return range;
        }
        // 否则从数据库中查询
        List<GoodsType> list = goodsTypeMapper.selectList(Wrappers.lambdaQuery(GoodsType.class)
                .eq(GoodsType::getParentId, 0));
        // 并存入redis
        redisTemplate.opsForList().leftPush(Constant.ALL_PTYPE, list);

        List range = redisTemplate.opsForList().range(Constant.ALL_PTYPE, 0, -1);
        System.out.println("range = " + range);
        return range;
    }

    @Transactional
    @Override
    public void addEntity(GoodsTypeDTO goodsTypeDTO) {
        Asserts.fail( Objects.isNull(goodsTypeDTO.getTypeName())
                || goodsTypeDTO.getTypeName().equals("")
                || Objects.isNull(goodsTypeDTO), ResultCodeEnum.NO_DATA);

//         在缓存中查询父品类是否存在，存在则提示用户重复添加
        List range = redisTemplate.opsForList().range(Constant.ALL_PTYPE, 0, -1);
        List list = (List) range.get(0);

        for (int i = 0; i < list.size(); i++) {
//            System.out.println("redis中的类对象" + list.get(i).getClass());
//            System.out.println("容器中的类对象" + GoodsType.class);
//            System.out.println("redis中的类加载器" + list.get(i).getClass().getClassLoader());
//            System.out.println("容器中的类加载器" + GoodsType.class.getClassLoader());

            GoodsType goodsType = JSONUtil.toBean( JSONUtil.toJsonStr(list.get(i)),GoodsType.class) ;
            Asserts.fail(goodsType.getTypeName().equals(goodsTypeDTO.getTypeName()), ResultCodeEnum.TYPE_ALREADY_EXISTS);
        }

        // 不存在才添加
        GoodsType goodsType = BeanUtil.copyProperties(goodsTypeDTO, GoodsType.class);
        goodsType.setParentId(0);
        goodsTypeMapper.insert(goodsType);

        for (int i = 0; i < goodsTypeDTO.getSubTypes().size(); i++) {
            if (goodsTypeDTO.getSubTypes().get(i).equals("")
                    || Objects.isNull(goodsTypeDTO.getSubTypes().get(i))) continue;
            GoodsType subType = new GoodsType();
            subType.setTypeName(goodsTypeDTO.getSubTypes().get(i));
            subType.setParentId(goodsType.getId());
            goodsTypeMapper.insert(subType);
        }
    }

    @Transactional
    @Override
    public void upgradeById(GoodsTypeDTO goodsTypeDTO) {

        Asserts.fail( Objects.isNull(goodsTypeDTO.getTypeName())
                || goodsTypeDTO.getTypeName().equals("")
                || Objects.isNull(goodsTypeDTO), ResultCodeEnum.NO_DATA);

//         在缓存中查询父品类是否存在，存在则提示用户重复添加
        List range = redisTemplate.opsForList().range(Constant.ALL_PTYPE, 0, -1);
        List list = (List) range.get(0);

        for (int i = 0; i < list.size(); i++) {
            GoodsType goodsType = (GoodsType) list.get(i);
            Asserts.fail(goodsType.getTypeName().equals(goodsTypeDTO.getTypeName()) &&
                    !goodsType.getId().equals(goodsTypeDTO.getId()), ResultCodeEnum.TYPE_ALREADY_EXISTS);
        }

        goodsTypeMapper.deleteSubType(goodsTypeDTO.getId());

        GoodsType type = new GoodsType();
        BeanUtil.copyProperties(goodsTypeDTO, type);
        goodsTypeMapper.updateById(type);

        List<String> types = goodsTypeDTO.getSubTypes();
        types.forEach(e -> {
            GoodsType goodsType = new GoodsType();
            goodsType.setParentId(goodsTypeDTO.getId());
            goodsType.setTypeName(e);
            goodsTypeMapper.insert(goodsType);
        });
    }

    // 根据父id找子品类
    @Override
    public List<GoodsType> getAllSubTypes(Integer id) {

        List<GoodsType> types
                = goodsTypeMapper.selectList(Wrappers.lambdaQuery(GoodsType.class)
                .eq(GoodsType::getParentId, id));
        return types;
    }

    // 为父品类找子品类
    private List<GoodsTypeVO> getSubType(List<GoodsTypeVO> levelOne, List<GoodsType> allType){
        levelOne.forEach(e -> {
            // 遍历找出子权限
            List<GoodsTypeVO> childrenType = allType.stream()
                    .filter(n -> e.getId() == n.getParentId())
                    .map(m -> {
                        GoodsTypeVO goodsTypeVO1 = new GoodsTypeVO();
                        BeanUtil.copyProperties(m, goodsTypeVO1);
                        return goodsTypeVO1;
                    })
                    .collect(Collectors.toList());
            if (childrenType != null && childrenType.size() > 0){
                getSubType(childrenType, allType);
            }
            e.setGoodsList(childrenType);
        });
        return levelOne;
    }
}
